// Copyright (C) ZHENG Zhong <heavyzheng nospam-at gmail D0T com>
// http://www.zhengzhong.net/
//
// $Id: create_dom_tree.hpp 318 2009-03-02 14:03:21Z heavyzheng $
//

#ifndef ZZHENG_EXAMPLE_CREATE_DOM_TREE_HPP_20080806__
#define ZZHENG_EXAMPLE_CREATE_DOM_TREE_HPP_20080806__

#include <zzheng/xml/dom.hpp>

#include <cassert>
#include <exception>
#include <memory>
#include <string>
#include <vector>
#include <iostream>

namespace zzheng {
namespace example {

    struct cd_info {

        explicit cd_info(const std::string& title,
                         const std::string& artist,
                         const std::string& year)
        : title_(title), artist_(artist), year_(year) {
            // Do nothing.
        }

        std::string title_;
        std::string artist_;
        std::string year_;

    }; // struct cd_info

    inline
    void fill_cd_catalog(std::vector<cd_info>& cds) {
        cds.push_back( cd_info("A night at the opera", "Queen",   "1975") );
        cds.push_back( cd_info("Never mind",           "Nirvana", "1991") );
    }

    ////////////////////////////////////////////////////////////////////////////////////////////////

    inline
    int create_dom_tree_no_ns() {

        std::vector<cd_info> cds;
        fill_cd_catalog(cds);

        try {
            // Create an XML document with a root element "cd_catalog".
            xml::dom::document doc;
            xml::dom::element_ptr root = doc.reset_root( xml::dom::make_element("cd_catalog") );

            // For each cd_info object, create a child element "cd" under the root "cd_catalog".
            for (std::vector<cd_info>::iterator i = cds.begin(); i != cds.end(); ++i) {
                xml::dom::element_ptr cd = root->children().push_back(xml::dom::make_element("cd"));
                cd->children().push_back(xml::dom::make_element("title"))->set_content(i->title_);
                cd->children().push_back(xml::dom::make_element("artist"))->set_content(i->artist_);
                cd->children().push_back(xml::dom::make_element("year"))->set_content(i->year_);
            }

            std::cout << doc.str() << std::endl;
            // doc.save_to_file("file_name.xml");
            return 0;

        } catch (const xml::dom::dom_error& ex) {
            std::cerr << "Error (dom_error): " << ex.what() << std::endl;
            return 1;
        } catch (const std::exception& ex) {
            std::cerr << "Error (std::exception): " << ex.what() << std::endl;
            return 1;
        } catch (...) {
            std::cerr << "Error (unknown exception)" << std::endl;
            return 1;
        }
    }

    inline
    int create_dom_tree_ns() {

        std::vector<cd_info> cds;
        fill_cd_catalog(cds);

        const std::string ROOT_URI = "http://www.foo.com/cd_catalog/";
        const std::string CD_URI   = "http://www.foo.com/cd/";

        try {
            xml::dom::document doc;
            xml::dom::element_ptr root = doc.reset_root( xml::dom::make_element("cd_catalog") );
            root->set_uri(ROOT_URI);

            typedef std::vector<cd_info>::iterator iterator;
            for (iterator i = cds.begin(); i != cds.end(); ++i) {
                xml::dom::element_ptr cd = root->children()
                                                .push_back( xml::dom::make_element(CD_URI, "cd") );
                cd->children().push_back( xml::dom::make_element(CD_URI, "title") )
                  ->children().push_back( xml::dom::make_text(i->title_) );
                cd->children().push_back( xml::dom::make_element(CD_URI, "artist") )
                  ->children().push_back( xml::dom::make_text(i->artist_) );
                cd->children().push_back( xml::dom::make_element(CD_URI, "year") )
                  ->children().push_back( xml::dom::make_text(i->year_) );
            }

            std::cout << doc.str() << std::endl;
            // doc.save_to_file("file_name.xml");
            return 0;

        } catch (const xml::dom::dom_error& ex) {
            std::cerr << "Error (dom_error): " << ex.what() << std::endl;
            return 1;
        } catch (const std::exception& ex) {
            std::cerr << "Error (std::exception): " << ex.what() << std::endl;
            return 1;
        } catch (...) {
            std::cerr << "Error (unknown exception)" << std::endl;
            return 1;
        }
    }

} // namespace zzheng::example
} // namespace zzheng


#endif // ZZHENG_EXAMPLE_CREATE_DOM_TREE_HPP_20080806__



